List

A list is a generic vector containing other objects.

For example, the following variable x is a list containing copies of three vectors n , s , b , and a numeric value 3.

> n = c(2, 3, 5) 
> s = c("aa", "bb", "cc", "dd", "ee") 
> b = c(TRUE, FALSE, TRUE, FALSE, FALSE) 
> x = list(n, s, b, 3)   # x contains copies of n, s, b

List Slicing

We retrieve a list slice with the single square bracket "[]" operator. The following is a slice containing the second member of x , which is a copy of s .

> x[2] 
[[1]] 
[1] "aa" "bb" "cc" "dd" "ee"

With an index vector, we can retrieve a slice with multiple members. Here a slice containing the second and fourth members of x .

> x[c(2, 4)] 
[[1]] 
[1] "aa" "bb" "cc" "dd" "ee" 
 
[[2]] 
[1] 3

Member Reference

In order to reference a list member directly, we have to use the double square bracket "[[]]" operator. The following object x[[2]] is the second member of x . In other words, x[[2]] is a copy of s , but is not a slice containing s or its copy.

> x[[2]] 
[1] "aa" "bb" "cc" "dd" "ee"

We can modify its content directly.

> x[[2]][1] = "ta" 
> x[[2]] 
[1] "ta" "bb" "cc" "dd" "ee" 
> s 
[1] "aa" "bb" "cc" "dd" "ee"   # s is unaffected

Named List Members

We can assign names to list members, and reference them by names instead of numeric indexes.

For example, in the following, v is a list of two members, named "bob" and "john" .

> v = list(bob=c(2, 3, 5), john=c("aa", "bb")) 
> v 
$bob 
[1] 2 3 5 
 
$john 
[1] "aa" "bb"

List Slicing

We retrieve a list slice with the single square bracket "[]" operator. Here is a list slice containing a member of v named "bob".

> v["bob"] 
$bob 
[1] 2 3 5

With an index vector, we can retrieve a slice with multiple members. Here is a list slice with both members of v . Notice how they are reversed from their original positions in v .

> v[c("john", "bob")] 
$john 
[1] "aa" "bb" 
 
$bob 
[1] 2 3 5

Member Reference

In order to reference a list member directly, we have to use the double square bracket "[[]]" operator. The following references a member of v by name.

> v[["bob"]] 
[1] 2 3 5

A named list member can also be referenced directly with the "$" operator in lieu of the double square bracket operator.

> v$bob 
[1] 2 3 5

Search Path Attachment

We can attach a list to the R search path and access its members without explicitly mentioning the list. It should to be detached for cleanup.

> attach(v) 
> bob 
[1] 2 3 5 
> detach(v)

Difference Between [] And [[]] Notations For Accessing The Elements Of A List

The significant differences between the two methods are the class of the objects they return when used for extraction and whether they may accept a range of values, or just a single value during assignment.

Consider the case of data extraction on the following list:

foo <- list( str='R', vec=c(1,2,3), bool=TRUE )

Say we would like to extract the value stored by bool from foo and use it inside an if() statement. This will illustrate the differences between the return values of [] and [[]] when they are used for data extraction. The [] method returns objects of class list (or data.frame if foo was a data.frame) while the [[]] method returns objects whose class is determined by the type of their values.

So, using the [] method results in the following:

if( foo[ 'bool' ] ){ print("Hi!") }
Error in if (foo["bool"]) { : argument is not interpretable as logical

class( foo[ 'bool' ] )
[1] "list"

This is because the [] method returned a list and a list is not valid object to pass directly into an if() statement. In this case we need to use [[]] because it will return the "bare" object stored in 'bool' which will have the appropriate class:

if( foo[[ 'bool' ]] ){ print("Hi!") }
[1] "Hi!"

class( foo[[ 'bool' ]] )
[1] "logical"

The second difference is that the [] operator may be used to access a range of slots in a list or columns in a data frame while the [[]] operator is limited to accessing a single slot or column. Consider the case of value assignment using a second list, bar():

bar <- list( mat=matrix(0,nrow=2,ncol=2), rand=rnorm(1) )

Say we want to overwrite the last two slots of foo with the data contained in bar. If we try to use the [[]] operator, this is what happens:

foo[[ 2:3 ]] <- bar
Error in foo[[2:3]] <- bar : 
more elements supplied than there are to replace

This is because [[]] is limited to accessing a single element. We need to use []:

foo[ 2:3 ] <- bar
print( foo )

$str
[1] "R"

$vec
     [,1] [,2]
[1,]    0    0
[2,]    0    0

$bool
[1] -0.6291121

Note that while the assignment was successful, the slots in foo kept their original names.